package bkhech.generator.mp.service;

import bkhech.generator.mp.config.GenConfig;
import bkhech.generator.mp.domain.GenTable;
import bkhech.generator.mp.domain.GenTableColumn;
import bkhech.generator.mp.mapper.GenTableColumnMapper;
import bkhech.generator.mp.mapper.GenTableMapper;
import bkhech.generator.mp.util.GenUtils;
import bkhech.generator.mp.util.VelocityInitializer;
import bkhech.generator.mp.util.VelocityUtils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.springframework.stereotype.Component;

import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * 业务 服务层实现
 *
 * @author bkhech
 */
@Slf4j
@RequiredArgsConstructor
@Component
public class GenTableService {
    private final GenTableMapper baseMapper;
    private final GenTableColumnMapper columnMapper;

    /**
     * 生成代码（自定义路径）
     */
    public void generatorCode() {
        final List<String> tableNames = GenConfig.tables;
        if (CollUtil.isEmpty(tableNames)) {
            throw new RuntimeException("请配置要生成的表名");
        }
        final List<GenTable> genTables = getGenTables(tableNames);
        for (GenTable table : genTables) {
            VelocityInitializer.initVelocity();
            VelocityContext context = VelocityUtils.prepareContext(table);
            // 获取模板列表
            List<String> templates = VelocityUtils.getTemplateList();
            for (String template : templates) {
                // 渲染模板
                StringWriter sw = new StringWriter();
                try {
                    Template tpl = Velocity.getTemplate(template, StandardCharsets.UTF_8.name());
                    tpl.merge(context, sw);
                } catch (ResourceNotFoundException e) {
                    log.error("渲染模板失败，表名：" + table.getTableName() + ", 模板【" + template + "】不存在， 跳过继续执行！！！异常信息：" + e.getMessage());
                    continue;
                }
                try {
                    String path = getGenPath(table, template);
                    FileUtil.writeUtf8String(sw.toString(), path);
                } catch (Exception e) {
                    throw new RuntimeException("渲染模板失败，表名：" + table.getTableName());
                }
            }
        }
    }

    /**
     * 获取代码生成地址
     *
     * @param table    业务表信息
     * @param template 模板文件路径
     * @return 生成地址
     */
    public static String getGenPath(GenTable table, String template) {
        String genPath = table.getGenPath();
        return VelocityUtils.getFileName(template, table, genPath);
    }


    /**
     * 获取表结构元数据信息
     *
     * @param tableNames 表名称列表
     * @return 表结构元数据信息列表
     */
    public List<GenTable> getGenTables(List<String> tableNames) {
        final String[] tables = ArrayUtil.toArray(tableNames, String.class);
        final List<GenTable> tableList = baseMapper.selectDbTableListByNames(tables);
        try {
            for (GenTable table : tableList) {
                String tableName = table.getTableName();
                // 初始化表信息
                GenUtils.initTable(table);

                // 根据表名称查询列信息
                List<GenTableColumn> genTableColumns = columnMapper.selectDbTableColumnsByName(tableName);
                for (GenTableColumn column : genTableColumns) {
                    // 初始化列属性字段
                    GenUtils.initColumnField(column, table);
                }

                // 设置列信息
                table.setColumns(genTableColumns);

                // 设置主键列信息
                setPkColumn(table);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("获取表结构元数据信息失败：" + e.getMessage());
        }

        return tableList;
    }

    /**
     * 设置主键列信息
     *
     * @param table 业务表信息
     */
    public void setPkColumn(GenTable table) {
        for (GenTableColumn column : table.getColumns()) {
            if (column.isPk()) {
                table.setPkColumn(column);
                break;
            }
        }
        if (ObjectUtil.isNull(table.getPkColumn())) {
            table.setPkColumn(table.getColumns().get(0));
        }

    }


}

